﻿using System.Collections.Generic;
using Jay.Sc2.Bof.Lib.State;
using System;
using Jay.Sc2.Bof.Lib.Tools;

namespace Jay.Sc2.Bof.Lib.Action
{
	public abstract class Action : IAction
	{
		public virtual void Execute(IBuildOrder bo) { }
		public virtual bool CanExecute(IBuildOrder bo) { return HaveTechnology(bo) && HaveResources(bo) && !IsInvalid(bo); }
		public abstract bool HaveResources(IBuildOrder bo);
		public abstract bool HaveTechnology(IBuildOrder bo);
		public abstract bool IsInvalid(IBuildOrder bo);
		public virtual bool IsUseless(IBuildOrder bo, IGoal goal) { return false; }
		public virtual IAction[,] Requirements { get { return null; } }
		public virtual IAction[,] Inputs { get { return null; } }

		public Range InputRangeOf(IAction action)
		{
			IAction[,] inputs = Inputs;
			if (inputs == null) return new Range();
			Range range = new Range(int.MaxValue, int.MinValue);
			for (int c = 0; c < inputs.GetLength(0); c++)
			{
				int count = 0;
				for (int d = 0; d < inputs.GetLength(1); d++)
					if (inputs[c, d] == action) count++;
				if (count < range.Minimum) range.Minimum = count;
				if (count > range.Maximum) range.Maximum = count;
			}
			return range;
		}

		private List<IAction> m_AllRequirements;
		public IList<IAction> AllRequirements
		{
			get
			{
				if (m_AllRequirements == null && Requirements != null)
				{
					m_AllRequirements = new List<IAction>();
					foreach (IAction requirement in Requirements)
						if (!m_AllRequirements.Contains(requirement))
						{
							IList<IAction> requirements = requirement.AllRequirements;
							if (requirements != null)
								foreach (IAction required in requirements)
									if (!m_AllRequirements.Contains(required))
										m_AllRequirements.Add(required);
							m_AllRequirements.Add(requirement);
						}
				}
				return m_AllRequirements;
			}
		}

		public virtual string Name { get { return GetType().Name; } }
		public int CompareTo(IAction other) { return Name.CompareTo(other.Name); }

		public override bool Equals(object obj) { return GetType().Equals(obj.GetType()); }
		public override int GetHashCode() { return GetType().GetHashCode(); }
		public override string ToString() { return CleanName; }



		private static bool StartsWith(string text, string actionName)
		{
			if (actionName.StartsWith(text) && actionName.Length > text.Length && char.IsUpper(actionName[text.Length])) return true;
			return false;
		}
		public string CleanName
		{
			get
			{
				string actionName = Name;
				if (StartsWith("Action", actionName)) actionName = actionName.Substring(6);
				if (StartsWith("Upgrade", actionName)) actionName = actionName.Substring(7);
				if (StartsWith("Researched", actionName)) actionName = "+ " + actionName.Substring(10);
				if (StartsWith("Produce", actionName)) actionName = actionName.Substring(7);
				if (StartsWith("Spawn", actionName))
				{
					actionName = actionName.Substring(5);
					if (actionName == "Zergling") actionName = "+2 " + actionName;
					else actionName = "+1 " + actionName;
				}
				if (StartsWith("Switch", actionName)) actionName = actionName.Substring(6);
				if (StartsWith("Trick", actionName)) actionName = actionName.Substring(5);
				if (StartsWith("Harvest", actionName))
				{
					actionName = actionName.Substring(7);
					if (actionName.EndsWith("SCV")) actionName = actionName.Substring(0, actionName.Length - 3);
					if (actionName.EndsWith("Probe")) actionName = actionName.Substring(0, actionName.Length - 5);
					if (actionName.EndsWith("Drone")) actionName = actionName.Substring(0, actionName.Length - 5);
				}
				return actionName;
			}
		}
	}
}
